﻿using System;
using System.Collections.Generic;
using System.Linq;
using CID.Domain.Development;
using CID.Domain.Operations;
using CID.Execution.Controller.Support;
using CID.Execution.Support.Scripting;
using NUnit.Framework;

namespace CID.Execution.Controller.Tests.Support
{
    [TestFixture]
    class MasterDeactivationScriptTests : BaseControllerTests
    {
        private IEnvironment environment;
        private IRelease release;
        private IEnumerable<IComponent> components;
        private Guid deploymentUniqueIdentifier;

        public override void SetUp()
        {
            base.SetUp();
            environment = OperationsData.Environment;
            release = DevelopmentData.ActiveRelease;
            components = DevelopmentData.Components;
            deploymentUniqueIdentifier = Guid.NewGuid();
        }

        [Test]
        public void TestCreateNew_ShouldCreateDeactivationScriptPerComponent()
        {
            var script = new MasterDeactivationScript(deploymentUniqueIdentifier, release, components, environment);

            Assert.AreEqual(deploymentUniqueIdentifier, script.DeploymentUniqueIdentifier);
            Assert.AreEqual(release, script.Release);
            Assert.AreEqual(components.Count(), script.Steps.Count());
            CollectionAssert.AreEquivalent(components.Select(x => x.Name), script.Steps.Select(x => x.Component.Name));
            CollectionAssert.AllItemsAreInstancesOfType(script.Steps.ToArray(), typeof(DeactivationScriptStep));
        }


        [Test]
        public void TestCreateLocationSpecific_ShouldCreateLocationSpecificDeactivationScriptPerComponentIncluded()
        {
            var includedComponents = components.Where(x => ((x.Id == 2) || (x.Id == 3) || (x.Id == 6) || (x.Id == 7))).ToArray();
            var script = new MasterDeactivationScript(deploymentUniqueIdentifier, release, components, environment);

            var locationSpecificScript = script.CreateLocationSpecific(OperationsData.Location2, includedComponents);

            Assert.AreEqual(deploymentUniqueIdentifier, locationSpecificScript.DeploymentUniqueIdentifier);
            Assert.AreEqual(includedComponents.Count(), locationSpecificScript.Steps.Count());
            Assert.AreEqual(OperationsData.Location2.Id, locationSpecificScript.LocationId);
            Assert.AreEqual(release.Id, locationSpecificScript.Release.Id);
            CollectionAssert.AreEquivalent(includedComponents.Select(x => x.Name), locationSpecificScript.Steps.Select(x => x.Component.Name));
            CollectionAssert.AllItemsAreInstancesOfType(locationSpecificScript.Steps.ToArray(), typeof(DeactivationScriptStep));
            var serverRole1Components = includedComponents.Where(x => x.RequiredServerRole.Id == OperationsData.ServerRole1.Id).Select(x => x.Id).ToArray();
            var serverRole2Components = includedComponents.Where(x => x.RequiredServerRole.Id == OperationsData.ServerRole2.Id).Select(x => x.Id).ToArray();
            var serverRole3Components = includedComponents.Where(x => x.RequiredServerRole.Id == OperationsData.ServerRole3.Id).Select(x => x.Id).ToArray();
            var serverRole4Components = includedComponents.Where(x => x.RequiredServerRole.Id == OperationsData.ServerRole4.Id).Select(x => x.Id).ToArray();

            foreach (var step in locationSpecificScript.Steps)
            {
                if (serverRole1Components.Contains(step.Component.Id))
                    CollectionAssert.IsSubsetOf(step.TargetServers.Select(x => x.Name).ToArray(), OperationsData.ServerRole1.Assignments.Select(x => x.Server.Name).ToArray());
                if (serverRole2Components.Contains(step.Component.Id))
                    CollectionAssert.IsSubsetOf(step.TargetServers.Select(x => x.Name).ToArray(), OperationsData.ServerRole2.Assignments.Select(x => x.Server.Name).ToArray());
                if (serverRole3Components.Contains(step.Component.Id))
                    CollectionAssert.IsSubsetOf(step.TargetServers.Select(x => x.Name).ToArray(), OperationsData.ServerRole3.Assignments.Select(x => x.Server.Name).ToArray());
                if (serverRole4Components.Contains(step.Component.Id))
                    CollectionAssert.IsSubsetOf(step.TargetServers.Select(x => x.Name).ToArray(), OperationsData.ServerRole4.Assignments.Select(x => x.Server.Name).ToArray());
            }
        }
    }
}
